/////////////////////////////////////////////////////////////////////////////
// Name:        wininetinputstream.cpp
// Purpose:     MS-Windows native URL support based on WinINet
// Author:      Hajo Kirchhoff
// Modified by: yospaly
// Created:     06/11/2003
// Copyright:   (c) 2003 Hajo Kirchhoff
// Licence:     wxWindows licence
/////////////////////////////////////////////////////////////////////////////

#include <wx/wx.h>
#include <wx/uri.h>

#include "wininetstream.h"

size_t WinINetInputStream::GetSize() {
	if (_size>0) {
		return _size; 
	}
	
	DWORD size = 0;
	DWORD dwSize = sizeof(_size);
	DWORD index = 0;
	
	if ( _scheme==_T("http") ) {
		if (!HttpQueryInfo(_connection, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER,
				&_size, &dwSize, &index)) {
			_size = 0;
		}
	} else  if ( _scheme==_T("ftp") ) {
		_size = FtpGetFileSize(_connection, &size);
	}
	
	return _size;
}

size_t WinINetInputStream::OnSysRead(void *buffer, size_t bufsize) {
	DWORD bytesread = 0;
	if (!InternetReadFile(_connection, buffer, bufsize, &bytesread)) {
		DWORD lError = ::GetLastError();
		if (lError != ERROR_SUCCESS)
			SetError(wxSTREAM_READ_ERROR);

		DWORD iError, bLength;
		InternetGetLastResponseInfo(&iError, NULL, &bLength);
		if (bLength > 0) {
			wxString errorString;
			InternetGetLastResponseInfo(&iError, wxStringBuffer(errorString,
					bLength), &bLength);

			wxLogError(wxT("Read failed with error %d: %s"),
			iError, errorString.c_str());
		}
	}

	if (bytesread == 0) {
		SetError(wxSTREAM_EOF);
	}

	return bytesread;
}

wxString WinINetInputStream::CheckConnection() {
start:
	if (0 == _connection) {
		if (::GetLastError() == ERROR_INTERNET_EXTENDED_ERROR) {
			wxChar buf[2000];
			DWORD e, l = sizeof(buf);
			InternetGetLastResponseInfo(&e, buf, &l);

			return wxString::Format(_("Internet Error: %s"), buf);
		}
		
		return wxString::Format(_("Can't download from : %s !"), _url.c_str() );
	}
	
	DWORD type, type_s;
	type_s = sizeof(type);
	InternetQueryOption(_connection, INTERNET_OPTION_HANDLE_TYPE,
						&type, &type_s);

	switch (type) {
		case INTERNET_HANDLE_TYPE_HTTP_REQUEST:
		case INTERNET_HANDLE_TYPE_CONNECT_HTTP:
			type_s = sizeof(DWORD);
			if (HttpQueryInfo(_connection, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER,
					&type, &type_s, NULL)) {
				if (type == 401) { // authorization required
				} else if (type == 407) { // proxy authorization required
				} else if (type >= 300) {
					_connection = 0;
					goto start;
				}
			}
	}
	
	return wxString();
}

WinINetInputStream::WinINetInputStream(const wxString& url) {
	_size = 0;
	
	_url = url;
	_scheme = wxURI(url).GetScheme();
	_scheme.MakeLower();
	
	DWORD rc = InternetAttemptConnect(0);

	_internet = InternetOpen(wxVERSION_STRING, INTERNET_OPEN_TYPE_PRECONFIG,
			NULL, NULL, rc == ERROR_SUCCESS ? 0 : INTERNET_FLAG_OFFLINE
	);

	DWORD flags =
		//    INTERNET_FLAG_DONT_CACHE |
			INTERNET_FLAG_KEEP_CONNECTION |
			//   INTERNET_FLAG_PRAGMA_NOCACHE |
					//   INTERNET_FLAG_RELOAD |
					INTERNET_FLAG_EXISTING_CONNECT | INTERNET_FLAG_PASSIVE;

	_connection = InternetOpenUrl(_internet, url.c_str(), NULL, 0,
			flags, 0);
	
	DWORD timeout = 4000; // TimeOut
	// InternetSetOption(_connection, INTERNET_OPTION_RECEIVE_TIMEOUT, &timeout, sizeof(timeout));
}

WinINetInputStream::~WinINetInputStream() {
	if (_connection) {
		InternetCloseHandle(_connection);
		_connection = NULL;
	}
	if (_internet) {
		InternetCloseHandle(_internet);
		_internet = NULL;
	}
}
